#include "DM.h"
#include "static.h"
#include "opt.h"
#include "parser.h"
#include "parser_helper.h"
#include "message.h"
#include <cassert>
#include <string>
#include <iostream>
#include <sstream>

//----------------------------------------------------------------------------------------------------------//
class SortNode_C
{
    public:
        set<Node_C*> _setNode;
        queue<Node_C*> _qNode;
        Wire_C* _pCurWire;
        Node_C* _pCurNode;
};
//----------------------------------------------------------------------------------------------------------//
class SortInst_C
{
    public:
        map<Inst_C*,int> _mapInstFaninCNT;
        queue<Net_C*> _qNetToBeCheck;
};
//----------------------------------------------------------------------------------------------------------//
class DMMgr_C::Imp_C
{
    public: //data 
        map<string,PINode_C*> _mapPINode;
        map<string,PONode_C*> _mapPONode;
        map<string,PinNode_C*> _mapPinNode;
        vector<PinNode_C*> _vPinNode;
        map<string,InterNode_C*> _mapInterNode;
        vector<Wire_C*> _vWire;
        map<string,Inst_C*> _mapInst;
        vector<Inst_C*> _vInst;
        map<string,Net_C*> _mapNet;
        vector<Net_C*> _vNet;
        map<string,LibCell_C*> _mapLibCell;
        map<string,LibCellGrp_C*> _mapLibCellGrp;
        vector<Inst_C*> _vSeqInst;
        float _fClockPeriod; 
        vector<pair<string,string> > _vSize;
    
    public: //data - for buildDM
        ParserData_S* _pParserData;
        map<string,Node_C*> _mapNode;
        set<string> _setPI;
        set<string> _setPO;
        map<Node_C*,vector<Wire_C*> > _mapNodeWire;
        map<Wire_C*,pair<Node_C*,Node_C*> > _mapWireNode;
        
        SortNode_C* _pSortNode;
        SortInst_C* _pSortInst;
        int _nNodeCNT;
    
    public: //function
        Imp_C(ParserData_S* p_pParserData);
        void buildLibCells();
        void buildInsts();
        void buildNets();
        void buildPIPO();
        void buildNodes();
        void buildCons(const vector<SpefConnection>& p_rvCon,Net_C* p_pNet);
        void buildCaps(const vector<SpefCapacitance>& p_rvCap,Net_C* p_pNet);
        void buildRess(const vector<SpefResistance>& p_rvRes,Net_C* p_pNet);
        void buildLibCellGrp(LibCell_C* p_pLibCell);
        void buildPINode(const string& p_strName,Net_C* p_pNet);
        void buildPONode(const string& p_strName,Net_C* p_pNet);
        void buildPinNode(const string& p_strInstName,const string& p_strPinName,const char& p_cDir,Net_C* p_pNet);
        void buildInterNode(string p_strName,float p_fParasiticCap,Net_C* p_pNet);
        void buildWire(Node_C* p_pFromNode,Node_C* p_pToNode,float p_fRes);
        void setModuleBoundary();
        void sortNodes();
        void checkNode(Node_C*); //sub of sortNode
        bool isChecked(Node_C*); //sub of checkNode
        void connectDriversReceivers();
        void buildSeqInsts();
        void initNodeId();
        void initInstId();
        void buildPinNodeVector();
        void sortInstAndNet();
    
    private:
        void initInstFaninCNT(); //sub of sortInstAndNet 
        void collectFirstLv(); //sub of sortInstAndNet 
        void collectOtherLv(); //sub of sortInstAndNet
        bool isArrivePO(BoundaryNode_C* p_pBNode); //sub of sortInstAndNet
        bool isAllFaninCounted(Inst_C* p_pInst); //sub of sortInstAndNet
};
//----------------------------------------------------------------------------------------------------------//
DMMgr_C::Imp_C::Imp_C(ParserData_S* p_pParserData) : _pParserData(p_pParserData)
{
    _pSortNode = new SortNode_C;
    _pSortInst = new SortInst_C;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,PINode_C*>& DMMgr_C::getPINode() const 
{
    return _pImp->_mapPINode;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,PONode_C*>& DMMgr_C::getPONode() const 
{
    return _pImp->_mapPONode;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,PinNode_C*>& DMMgr_C::getPinNodeByMap() const 
{
    return _pImp->_mapPinNode;
}
//----------------------------------------------------------------------------------------------------------//
const vector<PinNode_C*>& DMMgr_C::getPinNodeByVector() const 
{
    return _pImp->_vPinNode;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,InterNode_C*>& DMMgr_C::getInterNode() const 
{
    return _pImp->_mapInterNode;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,Inst_C*>& DMMgr_C::getInstByMap() const 
{
    return _pImp->_mapInst;
}
//----------------------------------------------------------------------------------------------------------//
const vector<Inst_C*>& DMMgr_C::getInstByVector() const 
{
    return _pImp->_vInst;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,Net_C*>& DMMgr_C::getNetByMap() const 
{
    return _pImp->_mapNet;
}
//----------------------------------------------------------------------------------------------------------//
const vector<Net_C*>& DMMgr_C::getNetByVector() const 
{
    return _pImp->_vNet;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,LibCell_C*>& DMMgr_C::getLibCell() const 
{
    return _pImp->_mapLibCell;
}
//----------------------------------------------------------------------------------------------------------//
const map<string,LibCellGrp_C*>& DMMgr_C::getLibCellGrp() const 
{
    return _pImp->_mapLibCellGrp;
}
//----------------------------------------------------------------------------------------------------------//
const vector<Inst_C*>& DMMgr_C::getSeqInst() const 
{
    return _pImp->_vSeqInst;
}
//----------------------------------------------------------------------------------------------------------//
const float DMMgr_C::getClockPeriod() const
{
    return _pImp->_fClockPeriod;
}
//----------------------------------------------------------------------------------------------------------//
const vector<pair<string,string> >& DMMgr_C::getSize() const
{
    this->_pImp->_vSize.resize(this->_pImp->_vInst.size());
    for(unsigned int iInst=0;iInst<this->_pImp->_vInst.size();++iInst){
        Inst_C* pInst = this->_pImp->_vInst[iInst];
        this->_pImp->_vSize[iInst] = make_pair(pInst->getName(),pInst->getLibCell()->getName());
    }
    return this->_pImp->_vSize;
}
//----------------------------------------------------------------------------------------------------------//
DMMgr_C::DMMgr_C(ParserData_S* p_pParserData) : _pImp()
{
    assert(1==p_pParserData->_vModule.size());
    this->_pImp = new Imp_C(p_pParserData);
    _pImp->buildLibCells();
    _pImp->buildInsts();
    _pImp->buildNets();
    _pImp->buildPIPO();
    _pImp->buildNodes();
    _pImp->setModuleBoundary();
    _pImp->sortNodes();
    _pImp->connectDriversReceivers();
    _pImp->buildSeqInsts();
    _pImp->sortInstAndNet(); 
    _pImp->initNodeId();
    _pImp->initInstId();
    _pImp->buildPinNodeVector();
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::dumpLibCell()
{
    Dumper dumper("dumpDM_LibCell.txt");
    map<string,LibCellGrp_C*>::const_iterator it;
    for(it=_pImp->_mapLibCellGrp.begin();it!=_pImp->_mapLibCellGrp.end();++it){
        LibCellGrp_C* pLibCellGrp = it->second;
        dumper.write("Grp %s %d - fanin(%d)\n",pLibCellGrp->getName().c_str(),pLibCellGrp->getMaxIdx()+1,pLibCellGrp->getLibCell(0)->getNumFanin());
        for(unsigned int i=0;i<=pLibCellGrp->getMaxIdx();++i){
            dumper.write("\t%s\n",pLibCellGrp->getLibCell(i)->getName().c_str());
        }
    }
    InfoMsg("[DMMgr_C] dumpLibCell - dumpDM_LibCell.txt\n");
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::dumpInst()
{
    Dumper* pDumper = new Dumper("dumpDM_Inst.txt");
    pDumper->write("inst_name cell_name\n");
    pDumper->write("drivers\n");
    pDumper->write("receivers\n");
    pDumper->write("\n");
    map<string,Inst_C*>::const_iterator it;
    for(unsigned int i=0;i<_pImp->_vInst.size();++i){
        Inst_C* pInst = _pImp->_vInst[i];
        pInst->dump(pDumper);
    } 
    InfoMsg("[DMMgr_C] dumpInst - dumpDM_Inst.txt\n");
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::dumpNet()
{
    Dumper dumper("dumpDM_Net.txt");
    dumper.write("net_name\n");
    dumper.write("node_name cap / to_node_name res\n");
    dumper.write("\n");
    vector<Net_C*>::const_iterator it;
    for(it=_pImp->_vNet.begin();it!=_pImp->_vNet.end();++it){
        Net_C* pNet = *it;
        dumper.write("%s\n",pNet->getName().c_str());
        const vector<Node_C*>& vNode = pNet->getNode();
        for(unsigned int iNode=0;iNode<vNode.size();++iNode){
            Node_C* pNode = vNode[iNode];
            dumper.write("%s(%d) %.3f / ",pNode->getName().c_str(),pNode->getId(),pNode->getParasiticCap());
            const vector<Wire_C*>& vToWire = pNode->getToWire();
            for(unsigned int iWire=0;iWire<vToWire.size();++iWire){
                Wire_C* pWire = vToWire[iWire];
                dumper.write("%s(%d) %.3f ",pWire->getToNode()->getName().c_str(),pWire->getToNode()->getId(),pWire->getRes());
            }
            dumper.write("\n");
        }
        dumper.write("\n");
    }
    InfoMsg("[DMMgr_C] dumpNet - dumpDM_Net.txt\n");
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::dumpNode()
{
    Dumper* pDumper = new Dumper("dumpDM_Node.txt");
    pDumper->write("node (type)\ncap \nfrom_node res\nto_node res\n");
    pDumper->write("\n");
    map<string,Node_C*>::const_iterator it;
    for(it=this->_pImp->_mapNode.begin();it!=this->_pImp->_mapNode.end();++it){
        Node_C* pNode = it->second;
        pNode->dump(pDumper);
    }
    delete pDumper;
    InfoMsg("[DMMgr_C] dumpNode - dumpDM_Node.txt\n");
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::dumpTiming()
{
    char nameBM[64]; 
    strcpy(nameBM,Static_C::getOption("-benchmark").toCStr());
    //string nameDumper = strcat(strtok(nameBM,"."),".timing");
    string nameDumper = strcat(nameBM,".timing");
    Dumper* pDumper = new Dumper(nameDumper.c_str());
    pDumper->write("node rise_tran fall_tran rise_delay fall_delay\n");
    for(unsigned int iNet=0;iNet<this->_pImp->_vNet.size();++iNet){
        BoundaryNode_C* pFromNode = this->_pImp->_vNet[iNet]->getFromNode();
        pFromNode->dumpTiming(pDumper);
        for(unsigned int iNode=0;iNode<this->_pImp->_vNet[iNet]->getToNode().size();++iNode){
            BoundaryNode_C* pToNode = this->_pImp->_vNet[iNet]->getToNode()[iNode];
            pToNode->dumpTiming(pDumper);
        }
    }
    delete pDumper;
    InfoMsg("[DMMgr_C] dumpTiming - %s\n",nameDumper.c_str());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::dumpSize()
{
    string nameRootPath = Static_C::getOption("-path").toStr();
    string nameBM       = Static_C::getOption("-benchmark").toStr();
    string nameDumper   = nameRootPath +"/" +nameBM + "/" +nameBM +".size";
    Dumper* pDumper = new Dumper(nameDumper.c_str());
    for(unsigned int iInst=0;iInst<this->_pImp->_vInst.size();++iInst){
        this->_pImp->_vInst[iInst]->dumpLibCell(pDumper);
    }
    InfoMsg("[DMMgr_C] dumpSize - %s\n",nameDumper.c_str());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildLibCellGrp(LibCell_C* p_pLibCell)
{
    if(0==this->_mapLibCellGrp.count(p_pLibCell->getFootprint())){
        LibCellGrp_C* pLibCellGrp = new LibCellGrp_C(p_pLibCell->getFootprint());
        pLibCellGrp->addLibCell(p_pLibCell);
        this->_mapLibCellGrp.insert(make_pair(p_pLibCell->getFootprint(),pLibCellGrp));
    }
    else{
        LibCellGrp_C* pLibCellGrp = this->_mapLibCellGrp.find(p_pLibCell->getFootprint())->second;
        pLibCellGrp->addLibCell(p_pLibCell);
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildLibCells()
{
    vector<LibParserCellInfo>& vCell = this->_pParserData->_vCellLibrary;
    for(unsigned int iCell=0;iCell<vCell.size();++iCell){
        LibParserCellInfo* pParserCellInfo = &vCell[iCell];
        LibCell_C* pLibCell = new LibCell_C(pParserCellInfo);
        this->_mapLibCell.insert(make_pair(pLibCell->getName(),pLibCell));
        buildLibCellGrp(pLibCell);
    }
    map<string,LibCellGrp_C*>::const_iterator it;
    for(it=this->_mapLibCellGrp.begin();it!=this->_mapLibCellGrp.end();++it){
        it->second->sortLibCells();
    }
    InfoMsg("[DM] build %d LibCells, %d LibCellGrps\n",this->_mapLibCell.size(),this->_mapLibCellGrp.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildInsts()
{
    const vector<cellInst_C*>& vCellInst = this->_pParserData->_vModule[0]->getCellInst();
    for(unsigned int iInst=0;iInst<vCellInst.size();++iInst){
        cellInst_C* pCellInst = vCellInst[iInst];
        LibCell_C* pLibCell = this->_mapLibCell.find(pCellInst->getCellType())->second;
        assert(pLibCell);
        string strName = pCellInst->getCellInst();
        Inst_C* pInst = new Inst_C(strName,pLibCell);
        this->_mapInst.insert(make_pair(strName,pInst));
    }
    InfoMsg("[DM] build %d Insts\n",this->_mapInst.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildNets()
{
    const vector<string>& vNet = this->_pParserData->_vModule[0]->getNet();
    for(unsigned int iNet=0;iNet<vNet.size();++iNet){
        string strName = vNet[iNet];
        if(0==strcmp("ispd_clk",strName.c_str())) {continue;}
        Net_C* pNet = new Net_C(strName);
        this->_mapNet.insert(make_pair(strName,pNet));
    }
    InfoMsg("[DM] build %d Nets\n",this->_mapNet.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildPIPO()
{
    const vector<string>& vPI = this->_pParserData->_vModule[0]->getPI();
    for(unsigned int i=0;i<vPI.size();++i){
        this->_setPI.insert(vPI[i]);
    }
    const vector<string>& vPO = this->_pParserData->_vModule[0]->getPO();
    for(unsigned int i=0;i<vPO.size();++i){
        this->_setPO.insert(vPO[i]);
    }
    InfoMsg("[DM] build %d PIs, %d POs\n",this->_setPI.size(),this->_setPO.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildNodes()
{
    this->_nNodeCNT = 0;
    const vector<spefData_S*>& vSpefData = this->_pParserData->_vSpefData;
    for(unsigned int i=0;i<vSpefData.size();++i){
        string strNetName = vSpefData[i]->_strNetName;
        float fLumpedCap = vSpefData[i]->_fLumpedCap;
        const vector<SpefConnection>& vCon = vSpefData[i]->_vConnection;
        const vector<SpefCapacitance>& vCap = vSpefData[i]->_vCap;
        const vector<SpefResistance>& vRes = vSpefData[i]->_vRes;
        if(0==this->_mapNet.count(strNetName)) {assert(0);}
        Net_C* pNet = this->_mapNet.find(strNetName)->second;
        pNet->setLumpedCap(fLumpedCap);
        buildCons(vCon,pNet);
        buildCaps(vCap,pNet);
        buildRess(vRes,pNet);
    }
    InfoMsg("[DM] build %d Nodes\n",this->_nNodeCNT);
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildCons(const vector<SpefConnection>& p_rvCon,Net_C* p_pNet)
{
    for(unsigned int i=0;i<p_rvCon.size();++i){
        const SpefConnection& Con = p_rvCon[i];
        if(Con.nodeType=='P'){
            if(Con.direction=='I'){
                buildPINode(Con.nodeName.n1,p_pNet);
            }
            else if(Con.direction=='O'){
                buildPONode(Con.nodeName.n1,p_pNet);
            }
            else {assert(0);}
        }
        else if (Con.nodeType=='I'){
            buildPinNode(Con.nodeName.n1,Con.nodeName.n2,Con.direction,p_pNet);
        }
        else {assert(0);}
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildPINode(const string& p_strName,Net_C* p_pNet)
{
    assert(this->_setPI.count(p_strName)>0);
    PINode_C* pPINode = new PINode_C(p_strName);
    this->_nNodeCNT++;
    this->_mapPINode.insert(make_pair(p_strName,pPINode));
    this->_mapNode.insert(make_pair(p_strName,pPINode));
    p_pNet->setFromNode(pPINode);
    pPINode->setNet(p_pNet);
    p_pNet->addNode(pPINode);
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildPONode(const string& p_strName,Net_C* p_pNet)
{
    assert(0<this->_setPO.count(p_strName));
    PONode_C* pPONode = new PONode_C(p_strName);
    this->_nNodeCNT++;
    this->_mapPONode.insert(make_pair(p_strName,pPONode));
    this->_mapNode.insert(make_pair(p_strName,pPONode));
    p_pNet->addToNode(pPONode);
    pPONode->setNet(p_pNet);
    p_pNet->addNode(pPONode);
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildPinNode(const string& p_strInstName,const string& p_strPinName, const char& p_cDir,Net_C* p_pNet)
{
    assert(0<this->_mapInst.count(p_strInstName));
    Inst_C* pInst = this->_mapInst.find(p_strInstName)->second;
    string strNodeName = p_strInstName+":"+p_strPinName;
    PinNode_C* pPinNode;
    if('I'==p_cDir){
        pPinNode = new PinNode_C(strNodeName,p_strPinName,pInst,PinNode_C::eInput);
        pInst->addFromPinNode(pPinNode);
        p_pNet->addToNode(pPinNode);
        pPinNode->setNet(p_pNet);
        p_pNet->addNode(pPinNode);
    }
    else if('O'==p_cDir){
        pPinNode = new PinNode_C(strNodeName,p_strPinName,pInst,PinNode_C::eOutput);
        pInst->setToPinNode(pPinNode);
        p_pNet->setFromNode(pPinNode);
        pPinNode->setNet(p_pNet);
        p_pNet->addNode(pPinNode);
    }
    else {assert(0);}
    this->_mapPinNode.insert(make_pair(strNodeName,pPinNode));
    this->_mapNode.insert(make_pair(strNodeName,pPinNode));
    this->_nNodeCNT++;
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildCaps(const vector<SpefCapacitance>& p_rvCap,Net_C* p_pNet)
{
    for(unsigned int i=0;i<p_rvCap.size();++i){
        const string& strName1 = p_rvCap[i].nodeName.n1;
        const string& strName2 = p_rvCap[i].nodeName.n2;
        const double& dCap = p_rvCap[i].capacitance;
        if(0<this->_mapPinNode.count(strName1+":"+strName2)) { //PinNode
            PinNode_C* pPinNode = this->_mapPinNode.find(strName1+":"+strName2)->second;
            pPinNode->setParasiticCap(dCap);
            DebugMsg("[buildCaps] PinNode - %s %s\n",strName1.c_str(),strName2.c_str());
        }
        else if(0<this->_mapPINode.count(strName1) && 0==strName2.size()) { //PINode
            PINode_C* pPINode = this->_mapPINode.find(strName1)->second;
            pPINode->setParasiticCap(dCap);
            DebugMsg("[buildCaps] PINode - %s %s\n",strName1.c_str(),strName2.c_str());
        }
        else if(0<this->_mapPONode.count(strName1) && 0==strName2.size()) { //PONode
            PONode_C* pPONode = this->_mapPONode.find(strName1)->second;
            pPONode->setParasiticCap(dCap);
            DebugMsg("[buildCaps] PONode - %s %s\n",strName1.c_str(),strName2.c_str());
        }
        else { //InterNode
            buildInterNode(strName1+":"+strName2,dCap,p_pNet);
            DebugMsg("[buildCaps] InterNode - %s %s\n",strName1.c_str(),strName2.c_str());
        }
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildInterNode(string p_strName,float p_fParasiticCap,Net_C* p_pNet)
{
    InterNode_C* pInterNode = new InterNode_C(p_strName,p_fParasiticCap);
    this->_nNodeCNT++;
    p_pNet->addNode(pInterNode);
    this->_mapInterNode.insert(make_pair(p_strName,pInterNode));
    this->_mapNode.insert(make_pair(p_strName,pInterNode));
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildRess(const vector<SpefResistance>& p_rvRes,Net_C* p_pNet)
{
    for(unsigned int i=0;i<p_rvRes.size();++i){
        ostringstream ssFromNodeName,ssToNodeName;
        ssFromNodeName << p_rvRes[i].fromNodeName;
        ssToNodeName << p_rvRes[i].toNodeName;
        string strFromNodeName = ssFromNodeName.str();
        string strToNodeName = ssToNodeName.str();
        if(this->_mapNode.count(strFromNodeName)==0){
            DebugMsg("[buildRess] from:%s\n",strFromNodeName.c_str());
            buildInterNode(strFromNodeName,0.0,p_pNet);
        } 
        if(this->_mapNode.count(strToNodeName)==0){
            DebugMsg("[buildRess] to:%s\n",strToNodeName.c_str());
            buildInterNode(strToNodeName,0.0,p_pNet);
        }
        Node_C* pFromNode = this->_mapNode.find(strFromNodeName)->second;
        Node_C* pToNode = this->_mapNode.find(strToNodeName)->second;
        buildWire(pFromNode,pToNode,p_rvRes[i].resistance);
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildWire(Node_C* p_pFromNode,Node_C* p_pToNode,float p_fRes)
{
    Wire_C* pWire = new Wire_C(p_pFromNode,p_pToNode,p_fRes);
    this->_vWire.push_back(pWire);
    this->_mapNodeWire[p_pFromNode].push_back(pWire);
    this->_mapNodeWire[p_pToNode].push_back(pWire);
    this->_mapWireNode[pWire] = make_pair(p_pFromNode,p_pToNode);
    DebugMsg("[buildWire] from:%s to:%s res:%f\n",p_pFromNode->getName().c_str(),p_pToNode->getName().c_str(),p_fRes);
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::setModuleBoundary()
{
    //Node: Delay of PI and PO are neglected, because they are all zero in ISPD2013 Benchmark.
    //Period
    this->_fClockPeriod = this->_pParserData->_pSdcData->_pClkData->_fClockPeriod;
    //PI 
    int nPI_CNT(0);
    vector<std::pair<string,inputDriver_S*> >& vPI_DriverInfo = this->_pParserData->_pSdcData->_vInputDrive;
    for(unsigned int i=0;i<vPI_DriverInfo.size();++i){
       //inputDriver_S::_strPin;
        string namePI = vPI_DriverInfo[i].first;
        string nameCell = vPI_DriverInfo[i].second->_strCell;
        float fTransRise = vPI_DriverInfo[i].second->_fTransRise;
        float fTransFall = vPI_DriverInfo[i].second->_fTransFall;
        PINode_C* pPINode = this->_mapPINode.find(namePI)->second;
        LibCell_C* pLibCell = this->_mapLibCell.find(nameCell)->second;
        assert(pPINode);
        assert(pLibCell);
        pPINode->setLibCell(pLibCell);
        pPINode->setDriverTransRise(fTransRise);
        pPINode->setDriverTransFall(fTransFall);
        nPI_CNT++;
    }
   
    //PO
    int nPO_CNT(0);
    vector<std::pair<string,float> >& vPO_Load = this->_pParserData->_pSdcData->_vOutputLoadPair;
    for(unsigned int i=0;i<vPO_Load.size();++i){
        string namePO = vPO_Load[i].first;
        float fLoad = vPO_Load[i].second;
        PONode_C* pPONode = this->_mapPONode.find(namePO)->second;
        assert(pPONode);
        pPONode->setLoadCap(fLoad);
        nPO_CNT++;
    }
    InfoMsg("[DM] set #PI_Driver: %d ,#PO_Load: %d \n",nPI_CNT,nPO_CNT);
}
//----------------------------------------------------------------------------------------------------------//
bool DMMgr_C::Imp_C::isChecked(Node_C* p_pNode)
{
    if(0<this->_pSortNode->_setNode.count(p_pNode)){
        return true;
    } else {
        this->_pSortNode->_setNode.insert(p_pNode);
        this->_pSortNode->_qNode.push(p_pNode);
        return false;
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::checkNode(Node_C* p_pNode)
{
    if(!isChecked(p_pNode)){
        DebugMsg("[sortNodes][checkNode] %s\n",p_pNode->getName().c_str());
        this->_pSortNode->_pCurWire->setFromNode(this->_pSortNode->_pCurNode);
        this->_pSortNode->_pCurWire->setToNode(p_pNode);
        this->_pSortNode->_pCurNode->addToWire(this->_pSortNode->_pCurWire);
        p_pNode->setFromWire(this->_pSortNode->_pCurWire);
    } else {
        DebugMsg("[sortNodes][checkNode] %s visited\n",p_pNode->getName().c_str());
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::sortNodes()
{
    for(map<string,Net_C*>::const_iterator it=this->_mapNet.begin();it!=this->_mapNet.end();++it){
        DebugMsg("[sortNodes] net:%s\n",it->second->getName().c_str());
        assert(this->_pSortNode->_qNode.empty());
        this->_pSortNode->_setNode.clear();
        Net_C* pNet = it->second;
        pNet->resetNode();
        this->_pSortNode->_qNode.push(pNet->getFromNode());
        this->_pSortNode->_setNode.insert(pNet->getFromNode());
        while(1){
            this->_pSortNode->_pCurNode = this->_pSortNode->_qNode.front();
            pNet->addNode(this->_pSortNode->_pCurNode);
            this->_pSortNode->_qNode.pop();
            const vector<Wire_C*>& vWire = this->_mapNodeWire.find(this->_pSortNode->_pCurNode)->second;
            for(unsigned int iWire=0;iWire<vWire.size();++iWire){
                this->_pSortNode->_pCurWire = vWire[iWire];
                map<Wire_C*,pair<Node_C*,Node_C*> >::const_iterator itWireNode = this->_mapWireNode.find(this->_pSortNode->_pCurWire);
                assert(itWireNode!=this->_mapWireNode.end());
                Node_C* pNode_1 = itWireNode->second.first;
                Node_C* pNode_2 = itWireNode->second.second;
                checkNode(pNode_1);
                checkNode(pNode_2);
            }
            if(this->_pSortNode->_qNode.empty()) {break;}
        }
    }
    InfoMsg("[DM] sort nodes for %d Nets\n",this->_mapNet.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::connectDriversReceivers()
{
    map<string,Inst_C*>::iterator it;
    for(it=this->_mapInst.begin();it!=this->_mapInst.end();++it){
        Inst_C* pInst = it->second;
        const vector<PinNode_C*>& vFromPinNode = pInst->getFromNode();
        for(unsigned int i=0;i<vFromPinNode.size();++i){
            BoundaryNode_C* pBNode= vFromPinNode[i]->getNet()->getFromNode();
            if(pBNode->getType()!=Node_C::ePin) {continue;}
            PinNode_C* pPinNode = static_cast<PinNode_C*> (pBNode);
            pInst->addDriver(pPinNode->getInst());
        }
        const vector<BoundaryNode_C*>& vToNode = pInst->getToNode()->getNet()->getToNode();
        for(unsigned int i=0;i<vToNode.size();++i){
            BoundaryNode_C* pBNode = vToNode[i];
            if(pBNode->getType()!=Node_C::ePin) {continue;}
            PinNode_C* pPinNode = static_cast<PinNode_C*> (pBNode);
            pInst->addReceiver(pPinNode->getInst());
        }
    }
    InfoMsg("[DM] connect driver-receiver for %d Insts\n",this->_mapInst.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildSeqInsts()
{
    int nCNT(0);
    for(map<string,Inst_C*>::const_iterator it=this->_mapInst.begin();it!=this->_mapInst.end();++it){
        if(it->second->isSeq()){
            this->_vSeqInst.push_back(it->second);
            nCNT++;
        }
    }
    InfoMsg("[DM] build %d Seqs\n",this->_vSeqInst.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::initInstFaninCNT()
{
    for(map<string,Inst_C*>::const_iterator it=this->_mapInst.begin();it!=this->_mapInst.end();++it){
        if(!it->second->isSeq()){
            _pSortInst->_mapInstFaninCNT[it->second] = it->second->getLibCell()->getNumFanin();
        } else {
            _pSortInst->_mapInstFaninCNT[it->second] = it->second->getLibCell()->getNumFanin() -1;
        }
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::collectFirstLv()
{
    for(map<string,PINode_C*>::const_iterator it=this->_mapPINode.begin();it!=this->_mapPINode.end();++it){
        this->_pSortInst->_qNetToBeCheck.push(it->second->getNet());
        this->_vNet.push_back(it->second->getNet());
    }
    for(unsigned int iSeq=0;iSeq<this->_vSeqInst.size();++iSeq){
        this->_pSortInst->_qNetToBeCheck.push(this->_vSeqInst[iSeq]->getToNode()->getNet());
        this->_vNet.push_back(this->_vSeqInst[iSeq]->getToNode()->getNet());
    }
}
//----------------------------------------------------------------------------------------------------------//
bool DMMgr_C::Imp_C::isArrivePO(BoundaryNode_C* p_pBNode)
{
    if(Node_C::ePO==p_pBNode->getType()) {
        return true;
    } else {
        return false;
    }
}
//----------------------------------------------------------------------------------------------------------//
bool DMMgr_C::Imp_C::isAllFaninCounted(Inst_C* p_pInst)
{
    map<Inst_C*,int>::iterator it = _pSortInst->_mapInstFaninCNT.find(p_pInst);
    assert(it->second>0);
    if(0==--it->second){
        return true;
    } else {
        return false;
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::collectOtherLv()
{
    map<Inst_C*,int>::iterator it;
    while(1){
        if(_pSortInst->_qNetToBeCheck.empty()) {break;}
        Net_C* pCurNet = _pSortInst->_qNetToBeCheck.front();
        _pSortInst->_qNetToBeCheck.pop();
        const vector<BoundaryNode_C*>& vToNode = pCurNet->getToNode();
        for(unsigned int iToNode=0;iToNode<vToNode.size();++iToNode){
            BoundaryNode_C* pToNode = vToNode[iToNode];
            if(isArrivePO(pToNode)) {continue;}
            PinNode_C* pPinNode = static_cast<PinNode_C*> (pToNode);
            Inst_C* pInst = pPinNode->getInst();
            if(isAllFaninCounted(pInst)){
                this->_vInst.push_back(pInst);
                if(!pInst->isSeq()){
                    _pSortInst->_qNetToBeCheck.push(pInst->getToNode()->getNet());
                    this->_vNet.push_back(pInst->getToNode()->getNet());
                }
            }
        }
    }
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::sortInstAndNet()
{
    this->_vInst.resize(0);
    this->_vNet.resize(0);
    initInstFaninCNT();
    collectFirstLv();
    collectOtherLv();
    
    InfoMsg("[DM] sort %d Nets\n",this->_vNet.size());
    InfoMsg("[DM] sort %d Insts\n",this->_vInst.size());
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::initInstId()
{   
    int nId(0);
    for(unsigned int iInst=0;iInst<this->_vInst.size();++iInst){
        this->_vInst[iInst]->setId(nId++);
    }
    InfoMsg("[DM] initInstId: 0 to %d\n",nId-1);
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::initNodeId()
{
    int nId(0);
    for(map<string,PINode_C*>::iterator it=this->_mapPINode.begin();it!=this->_mapPINode.end();++it){
        const vector<Node_C*>& vNode = it->second->getNet()->getNode();
        for(unsigned int iNode=0;iNode<vNode.size();++iNode){
            vNode[iNode]->setId(nId++);
        }
    }
    for(unsigned int iInst=0;iInst<this->_vInst.size();++iInst){
        const vector<Node_C*>& vNode = this->_vInst[iInst]->getToNode()->getNet()->getNode();
        for(unsigned int iNode=0;iNode<vNode.size();++iNode){
            vNode[iNode]->setId(nId++);
        }
    }
    InfoMsg("[DM] initNodeId: 0 to %d\n",nId-1);
}
//----------------------------------------------------------------------------------------------------------//
void DMMgr_C::Imp_C::buildPinNodeVector()
{
    int iPinNode(0);
    this->_vPinNode.resize(this->_mapPinNode.size());
    for(map<string,PinNode_C*>::const_iterator it=this->_mapPinNode.begin();it!=this->_mapPinNode.end();++it){
        this->_vPinNode[iPinNode++] = it->second;
    }
}
//----------------------------------------------------------------------------------------------------------//




